// 高级类型   ===============================
var __extends = (this && this.__extends) || (function () {
    var extendStatics = function (d, b) {
        extendStatics = Object.setPrototypeOf ||
            ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
            function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
        return extendStatics(d, b);
    };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
// 可以为null的类型 + 字符串字面量类型
// 联合类型 string | number
function padLeft(value, padding) {
    if (typeof padding === 'number') {
        return Array(padding + 1).join(' ') + value;
    }
    if (typeof padding === 'string') {
        return padding + value;
    }
    throw new Error('Expected string or number got ' + padding);
}
console.log(padLeft('hello hardy', true));
function getSmallPet() { }
var pet = getSmallPet();
pet.layEggs(); // 能调到
pet.fly(); // 调不到
// 因为声明类型是Fish | Bird，所以只能调用到公有的部分
// 一般在js中会这么写 , 可以加上类型断言防止取属性报错
if (pet.swim) {
    pet.swim();
}
else if (pet.fly) {
    pet.fly();
}
// 在ts中可以这么写
function isFish(pet) {
    return pet.swim !== undefined;
}
// 然后上面的代码可以改成
if (isFish(pet)) {
    pet.swim();
}
else {
    pet.fly();
}
// ---重写上面的例子
function isNumber(x) {
    return typeof x === 'number';
}
function isString(x) {
    return typeof x === 'string';
}
function padLeft1(value, padding) {
    if (isNumber(padding)) {
        return;
    }
    if (isString(padding)) {
        throw new Error("Expected string or number got " + padding);
    }
    // 交叉类型
    function extend(first, second) {
        var result = {}; // 类型断言
        for (var id in first) {
            result[id] = first[id];
        }
        for (var id in second) {
            if (!result.hasOwnProperty(id)) {
                result[id] = second[id];
            }
        }
        return result;
    }
    // ------------------------------
    var Person = /** @class */ (function () {
        function Person(name) {
            this.name = name;
        }
        return Person;
    }());
    var Consolelogabal = /** @class */ (function () {
        function Consolelogabal() {
        }
        Consolelogabal.prototype.log = function () { };
        return Consolelogabal;
    }());
    var jim = extend(new Person('hardy'), new Consolelogabal());
    jim.name = '小方块';
    jim.log();
    // 类型推断
    var Animal = /** @class */ (function () {
        function Animal() {
        }
        return Animal;
    }());
    var Tigger = /** @class */ (function (_super) {
        __extends(Tigger, _super);
        function Tigger() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        return Tigger;
    }(Animal));
    var Lion = /** @class */ (function (_super) {
        __extends(Lion, _super);
        function Lion() {
            return _super !== null && _super.apply(this, arguments) || this;
        }
        return Lion;
    }(Animal));
    function create1() {
        return [new Tigger(), new Lion()];
    }
    // 泛型约束
    // 工厂函数中的应用
    function create(c) {
        return new c();
    }
    // 泛型K受T约束
    function getProperty(obj, key) {
        return obj[key];
    }
    var x = { a: 1, b: 2, c: 3 };
    getProperty(x, 'a');
    function loggingIdentify(arg) {
        console.log(arg.length);
        return arg;
    }
    //泛型类
    var GenericNumber = /** @class */ (function () {
        function GenericNumber() {
        }
        return GenericNumber;
    }());
    // 给泛型定义number
    var genericNumber = new GenericNumber();
    genericNumber.zeroValue = 1;
    genericNumber.add = function (x, y) {
        return x + y;
    };
    //给泛型定义字符串
    var genericNumber2 = new GenericNumber();
    genericNumber2.zeroValue = 'hardy';
    genericNumber2.add = function (x, y) {
        return x + y + '小方块';
    };
    // -------------------
    function identify(args) {
        return args;
    }
    var myIdentify = identify;
    var Handler = /** @class */ (function () {
        function Handler() {
        }
        Handler.prototype.onClickBad = function (e) {
            this.type = e.type;
        };
        return Handler;
    }());
    var h = new Handler();
    var uiElement = {
        addClickListener: function () { }
    };
    uiElement.addClickListener(h.onClickBad);
    var desk = {
        suits: ['hearts', 'spades', 'clubs', 'diamonds'],
        cards: Array(52),
        createPickerCard: function () {
            var _this = this;
            return function () {
                var pickerCard = Math.floor(Math.random() * 52);
                var cardPicker = Math.floor(pickerCard / 13);
                return {
                    suit: _this.suits[cardPicker],
                    card: pickerCard % 13
                };
            };
        }
    };
    var cardPicker = desk.createPickerCard();
    var pickerCard = cardPicker();
    console.log('card:', pickerCard.card + '===' + pickerCard.suit);
    // 可选参数 和默认参数
    // 可选参数参数后+?
    function buildName(firstName, lastName) {
        var args = [];
        for (var _i = 2; _i < arguments.length; _i++) {
            args[_i - 2] = arguments[_i];
        }
        return firstName + "-" + lastName;
    }
    var name1 = buildName('hardy1');
    var name2 = buildName('hardy1', 'hardy2');
    var name3 = buildName('hardy1', 'hardy2', 'hardy3');
    var buildName1 = buildName;
    // 命名函数
    function add(x, y) {
        return x + y;
    }
    //匿名函数
    var myFunction = function (x, y) {
        return x + y;
    };
}
